#include "bsp_spi1_dma.h"
#include "at32f403a_407.h"
#include "cbb_init.h" 

void bsp_spi1_dma_init(void){

    // 使能时钟
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

    // 配置 SCK 引脚
    gpio_init_type gpio_init_struct;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_5;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);

    // 配置 MISO 引脚
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_6;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);
  
    // 配置 MOSI 引脚
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_7;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);

    // 配置SPI1
    spi_init_type spi_init_struct;
    spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
    spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
    spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
    spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
    spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_2;
    spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;
    spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
    spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
    spi_init(SPI1, &spi_init_struct);
  
    // 配置DMA1_CH3 -- SPI1_TX
    dma_init_type dma_init_struct;
    dma_init_struct.peripheral_base_addr = (uint32_t)&SPI1->dt;
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_LOW;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL3, &dma_init_struct);
    dma_flexible_config(DMA1, FLEX_CHANNEL3, DMA_FLEXIBLE_SPI1_TX);

    // 使能SPI1 DMA
    spi_i2s_dma_transmitter_enable(SPI1, TRUE);
    
    // 使能SPI1
    spi_enable(SPI1, TRUE);
}
INIT_PORT_BSP(bsp_spi1_dma_init);

uint8_t bsp_spi1_dma_transmit(uint8_t* pu8Data, uint32_t u32Len){
    
    // 关闭dma设置参数
    dma_channel_enable(DMA1_CHANNEL3, FALSE);
    spi_i2s_dma_transmitter_enable(SPI1, FALSE);
    
    // 设置dma地址
    DMA1_CHANNEL3->maddr = (uint32_t)pu8Data;
    
    // 设置dma传输长度
    DMA1_CHANNEL3->dtcnt = u32Len;

    // 开启dma
    spi_i2s_dma_transmitter_enable(SPI1, TRUE);
    dma_channel_enable(DMA1_CHANNEL3, TRUE);

    // 等待发送结束
    while(dma_flag_get(DMA1_FDT3_FLAG) == RESET);
    dma_flag_clear(DMA1_FDT3_FLAG);

    // 发送完成
    while(SPI1->sts_bit.bf != RESET);

    // 发送成功
    return 1;
}
